package com.tceasy.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * 信号量方式线程工具
 * 使用流程：1、初始化 设置信号量大小和是否顺序执行,默认最大开启10个线程且遵循先后原则 3、提交任务 4、关闭线程池
 * Created by hacker on 2015/5/5.
 */
public class SemaphoreThreadUtil {
    private static final Logger logger= LoggerFactory.getLogger(SemaphoreThreadUtil.class);


    private Semaphore semaphore;
    private ExecutorService executorService;
    private String name="";
    private int size;


    /**
     * 初始化 设置信号量大小和是否顺序执行,默认最大开启10个线程且遵循先后原则
     */
    public SemaphoreThreadUtil(){
        size=100;
        semaphore=new Semaphore(100,true);
        executorService= Executors.newCachedThreadPool();
    }
    public SemaphoreThreadUtil(String name){
        this.name=name;
        size=100;
        semaphore=new Semaphore(100,true);
        executorService= Executors.newCachedThreadPool();
    }
    public SemaphoreThreadUtil(int size, String name, boolean fair){
        this.size=size;
        this.name=name;
        semaphore=new Semaphore(size,fair);
        executorService= Executors.newCachedThreadPool();
    }

    public void submit(final ThreadHandler handler){
        executorService.execute(new Runnable() {
            @Override
            public void run() {
            try {
                semaphore.acquire();//获取许可,如果没有剩余许可，则acquire会被阻塞
                logger.info("{}线程池最大处理数：{}，当前剩余剩余{}个",new Object[]{name,size,semaphore.availablePermits()});
                handler.execute();
            } catch (InterruptedException e) {
                logger.error("semaphoreThreadExecute exception", e);
            } finally {
                semaphore.release();//回收许可
            }
            }
        });
    }

    /**
     *不再接收新任务，当所有任务都执行完关闭线程池
     */
    public void destroy(){
        executorService.shutdown();
        while(!executorService.isTerminated());
    }

    /**
     * 强行关闭线程池
     */
    public void destoryHard(){
        List<Runnable> list= executorService.shutdownNow();
        logger.info("强行关闭线程池，有{}个未执行的任务：{}",list.size(),list);
    }

    public interface ThreadHandler{
        public void execute();
    }
}
